home *** CD-ROM | disk | FTP | other *** search
- //////////
- //
- // File: VRPreferences.c
- //
- // Contains: Functions for VRScript preferences management.
- //
- // Written by: Tim Monroe
- //
- // Copyright: © 1999 by Apple Computer, Inc., all rights reserved.
- //
- // Change History (most recent first):
- //
- // <5> 06/06/99 rtm added kVRPrefs_PromptUser option
- // <4> 06/05/99 rtm tweaked VRPrefs_Init so that default values are identical with the
- // hard-coded values of earlier versions of VRScript
- // <3> 06/04/99 rtm added functions to read and write preferences on Windows and MacOS
- // <2> 06/03/99 rtm added dialog box handling code
- // <1> 06/02/99 rtm first file
- //
- // This file defines functions that we use to manage the VRScript preferences. Currently we support
- // preferences that indicate the name and location of the script file associated with a VR movie, but
- // it would be easy to add other preferences as well.
- //
- // A word about terminology: on the Macintosh, we store our preferences in a file (typically in the
- // Preferences folder inside the System folder), which we hereafter call the "preferences file". On
- // Windows, we store our preferences in the registry database. Therefore, on Windows, there is really
- // no single preferences file that contains our application preferences. Nonetheless, in the comments
- // below (and in the naming of some of the functions), we shall refer to a preferences file; in general,
- // you can interpret this to mean: the persistent collection of data that stores the application
- // preferences (whether that collection is an actual file or a chunk of data in some other file).
- //
- // A good discussion of Mac-based preference handling is contained in Gary Woodcock's article in develop,
- // issue 18. I have occasionally used an idea or two from the source code that accompanies that article,
- // but in general I had to start from scratch, largely because he assumes that all preferences should be
- // stored in resources (a tactic that may be correct for Macintosh applications but which does not easily
- // translate to Windows).
- //
- //////////
-
-
- //////////
- //
- // header files
- //
- //////////
-
- #include "VRPreferences.h"
-
-
- //////////
- //
- // global variables
- //
- //////////
-
- VRScriptPrefsHdl gPreferences; // a handle to the global preferences record
- static UserItemUPP gUserItemUPP; // UPP to our user-item drawing procedure
-
- extern ModalFilterUPP gModalFilterUPP; // UPP to our custom dialog event filter
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Start-up and shut-down utilities.
- //
- // Use these functions to initialize and deinitialize our preference handling.
- //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- //////////
- //
- // VRPrefs_Init
- // Initialize the application's global preferences.
- //
- //////////
-
- void VRPrefs_Init (void)
- {
- Boolean myPrefsExist = false;
-
- // allocate a record to hold the application preferences information
- gPreferences = (VRScriptPrefsHdl)NewHandleClear(sizeof(VRScriptPrefsRec));
- if (gPreferences == NULL)
- QuitFramework(); // this should never happen; if it does, we are REALLY in trouble...
-
- // look for a preferences file
- myPrefsExist = VRPrefs_PrefsFileExists();
- if (myPrefsExist) {
- // if one exists, open it and read the existing preferences from it
- VRPrefs_ReadPrefsFile();
- (**gPreferences).fPrefsFileExists = true;
- (**gPreferences).fPrefsDataDirty = false;
- } else {
- // if none exists, initialize the application preferences to a default state
- (**gPreferences).fScriptLocType = kVRPrefs_DirOfMovieFile;
- (**gPreferences).fScriptNameType = kVRPrefs_UserSpecifiedName;
- (**gPreferences).fTurboMode = false;
- (**gPreferences).fVerboseMode = false;
- (**gPreferences).fPrefsFileExists = false;
- (**gPreferences).fPrefsDataDirty = false;
-
- if ((**gPreferences).fScriptNameType == kVRPrefs_UserSpecifiedName) {
- // make sure there is a default user-specified name
- BlockMove(kDefaultScriptFileName, &((**gPreferences).fScriptBaseName[1]), strlen(kDefaultScriptFileName));
- (**gPreferences).fScriptBaseName[0] = strlen(kDefaultScriptFileName);
- }
- }
-
- // allocate a routine descriptor for the user-item drawing procedure
- gUserItemUPP = NewUserItemProc(VRPrefs_DrawPrefsDialogUserItem);
- }
-
-
- //////////
- //
- // VRPrefs_Stop
- // Close down the application's global preferences.
- //
- //////////
-
- void VRPrefs_Stop (void)
- {
- if (gPreferences != NULL) {
- // if necessary, update the stored preferences data
- if ((**gPreferences).fPrefsDataDirty)
- VRPrefs_UpdatePrefsFile();
-
- // get rid of the global preferences record
- DisposeHandle((Handle)gPreferences);
- gPreferences = NULL;
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Dialog box utilities.
- //
- // Use these functions to display the Preferences dialog box and get the user's preferences from it.
- //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- //////////
- //
- // VRPrefs_ShowPrefsDialog
- // Display the Preferences dialog box and handle events in it.
- //
- //////////
-
- void VRPrefs_ShowPrefsDialog (void)
- {
- DialogPtr myDialog = NULL;
- DialogItemIndex myItem = 0;
- DialogItemType myItemType;
- Handle myItemHandle = NULL;
- Rect myItemRect;
- short myIndex;
- OSErr myErr = noErr;
-
- if (gPreferences == NULL)
- return;
-
- // open up the Preferences dialog box
- myDialog = GetNewDialog(kPreferencesDialogID, NULL, (WindowPtr)-1L);
- if (myDialog == NULL)
- return;
-
- // set the current values into the dialog box
- VRPrefs_FillPrefsDialogFromPrefs(myDialog);
-
- // set the OK and Cancel buttons
- SetDialogDefaultItem(myDialog, kPrefsButtonDone);
- SetDialogCancelItem(myDialog, kPrefsButtonCancel);
-
- // set the drawing procedure for the two user items
- GetDialogItem(myDialog, kPrefsFilePathUserItem, &myItemType, &myItemHandle, &myItemRect);
- SetDialogItem(myDialog, kPrefsFilePathUserItem, myItemType, (Handle)gUserItemUPP, &myItemRect);
-
- GetDialogItem(myDialog, kPrefsFileNameUserItem, &myItemType, &myItemHandle, &myItemRect);
- SetDialogItem(myDialog, kPrefsFileNameUserItem, myItemType, (Handle)gUserItemUPP, &myItemRect);
-
- // show the dialog
- MacShowWindow(myDialog);
-
- // handle dialog box events until the user selects OK or Cancel
- do {
- ModalDialog(gModalFilterUPP, &myItem);
-
- switch (myItem) {
- // the script-file-location set of radio buttons
- case kPrefsRadioPromptUser:
- case kPrefsRadioDirOfMovieFile:
- case kPrefsRadioDirOfApplication:
- case kPrefsRadioUserSpecifiedPath:
- for (myIndex = kPrefsRadioPromptUser; myIndex <= kPrefsRadioUserSpecifiedPath; myIndex++) {
- GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- SetControlValue((ControlHandle)myItemHandle, (myIndex == myItem));
- }
-
- // enable script-file-name set of radio buttons, based on kPrefsRadioPromptUser
- for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) {
- GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- HiliteControl((ControlHandle)myItemHandle, ((myItem == kPrefsRadioPromptUser) ? 255 : 0));
- }
- break;
-
- // the script-file-name set of radio buttons
- case kPrefsRadioFileNamePlusVRS:
- case kPrefsRadioUserSpecifiedName:
- for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) {
- GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- SetControlValue((ControlHandle)myItemHandle, (myIndex == myItem));
- }
- break;
- }
-
- } while ((myItem != kPrefsButtonDone) && (myItem != kPrefsButtonCancel));
-
- // if the user selected OK, then retrieve the values from the dialog box and remember them
- if (myItem == kPrefsButtonDone) {
- // the script-file-location set of radio buttons
- for (myIndex = kPrefsRadioPromptUser; myIndex <= kPrefsRadioUserSpecifiedPath; myIndex++) {
- GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- if (GetControlValue((ControlHandle)myItemHandle) == 1) {
- (**gPreferences).fScriptLocType = myIndex - kPrefsRadioPromptUser;
- break;
- }
- }
-
- // the script-file-name set of radio buttons
- for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) {
- GetDialogItem(myDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- if (GetControlValue((ControlHandle)myItemHandle) == 1) {
- (**gPreferences).fScriptNameType = myIndex - kPrefsRadioFileNamePlusVRS;
- break;
- }
- }
-
- // the script directory pathname
- GetDialogItem(myDialog, kPrefsTextEditFilePath, &myItemType, &myItemHandle, &myItemRect);
- GetDialogItemText(myItemHandle, (**gPreferences).fScriptPathName);
-
- // the script name
- GetDialogItem(myDialog, kPrefsTextEditFileName, &myItemType, &myItemHandle, &myItemRect);
- GetDialogItemText(myItemHandle, (**gPreferences).fScriptBaseName);
-
- // in theory, we should check that the user actually changed something; but for now
- // we'll just assume that something changed (mostly since it won't cost much to update
- // the stored preferences when we exit)
- (**gPreferences).fPrefsDataDirty = true;
- }
-
- DisposeDialog(myDialog);
- }
-
-
- //////////
- //
- // VRPrefs_FillPrefsDialogFromPrefs
- // Set the values of the Preferences dialog box controls based on the existing values in gPreferences.
- //
- //////////
-
- static void VRPrefs_FillPrefsDialogFromPrefs (DialogPtr theDialog)
- {
- DialogItemType myItemType;
- Handle myItemHandle = NULL;
- Rect myItemRect;
- short myIndex;
-
- if (gPreferences == NULL)
- return;
-
- if (theDialog == NULL)
- return;
-
- // do some bounds-checking on the radio button values
- if (((**gPreferences).fScriptLocType < kVRPrefs_PromptUser) || ((**gPreferences).fScriptLocType > kVRPrefs_UserSpecifiedPath))
- (**gPreferences).fScriptLocType = kVRPrefs_PromptUser;
-
- if (((**gPreferences).fScriptNameType < kVRPrefs_FileNamePlusTXT) || ((**gPreferences).fScriptNameType > kVRPrefs_UserSpecifiedName))
- (**gPreferences).fScriptNameType = kVRPrefs_FileNamePlusTXT;
-
- // set up the current values of the radio button sets
- for (myIndex = kPrefsRadioPromptUser; myIndex <= kPrefsRadioUserSpecifiedPath; myIndex++) {
- GetDialogItem(theDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- SetControlValue((ControlHandle)myItemHandle, (myIndex == (**gPreferences).fScriptLocType + kPrefsRadioPromptUser));
- }
-
- // enable script-file-name set of radio buttons, based on kPrefsRadioPromptUser
- for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) {
- GetDialogItem(theDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- HiliteControl((ControlHandle)myItemHandle, (((**gPreferences).fScriptLocType + kPrefsRadioPromptUser == kPrefsRadioPromptUser) ? 255 : 0));
- }
-
- for (myIndex = kPrefsRadioFileNamePlusVRS; myIndex <= kPrefsRadioUserSpecifiedName; myIndex++) {
- GetDialogItem(theDialog, myIndex, &myItemType, &myItemHandle, &myItemRect);
- SetControlValue((ControlHandle)myItemHandle, (myIndex == (**gPreferences).fScriptNameType + kPrefsRadioFileNamePlusVRS));
- }
-
- // set the script directory pathname
- GetDialogItem(theDialog, kPrefsTextEditFilePath, &myItemType, &myItemHandle, &myItemRect);
- SetDialogItemText(myItemHandle, (**gPreferences).fScriptPathName);
-
- // set the script basename
- GetDialogItem(theDialog, kPrefsTextEditFileName, &myItemType, &myItemHandle, &myItemRect);
- SetDialogItemText(myItemHandle, (**gPreferences).fScriptBaseName);
- }
-
-
- //////////
- //
- // VRPrefs_DrawUserItem
- // Draw any user items in the Preferences dialog box.
- //
- //////////
-
- static void VRPrefs_DrawPrefsDialogUserItem (WindowPtr theWindow, DialogItemIndex theItem)
- {
- DialogItemType myItemType;
- Handle myItemHandle = NULL;
- Rect myItemRect;
-
- if (theWindow == NULL)
- return;
-
- // draw a rectangle around the two user items
- if ((theItem == kPrefsFilePathUserItem) || (theItem == kPrefsFileNameUserItem)) {
- GetDialogItem((DialogPtr)theWindow, theItem, &myItemType, &myItemHandle, &myItemRect);
- MacFrameRect(&myItemRect);
- }
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Preferences file utilities.
- //
- // Use these functions to open the preferences file, read the data in it, and update that data.
- //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- //////////
- //
- // VRPrefs_PrefsFileExists
- // Does a preferences file for our application already exist on this machine?
- //
- //////////
-
- static Boolean VRPrefs_PrefsFileExists (void)
- {
- Boolean myFileExists = false;
-
- #if TARGET_OS_WIN32
- char mySubKeyName[] = kVRPrefs_PrefsKeyName;
- HKEY myKey;
-
- if (RegOpenKeyEx(HKEY_CURRENT_USER, mySubKeyName, 0L, KEY_ALL_ACCESS, &myKey) == ERROR_SUCCESS) {
- RegCloseKey(myKey);
- myFileExists = true;
- }
- #endif
-
- #if TARGET_OS_MAC
- FSSpec myFSSpec;
- OSErr myErr = noErr;
-
- //myErr = VRPrefs_GetPrefsFileFSSpec(kScriptFileCreator, kPrefsFileType, &myFSSpec);
- myErr = VRPrefs_GetPrefsFileFSSpec(kVRPrefs_PrefsFileName, &myFSSpec);
- myFileExists = (myErr == noErr);
- #endif
-
- return(myFileExists);
- }
-
- #if TARGET_OS_MAC
- //////////
- //
- // VRPrefs_GetPrefsFileFSSpec
- // Return, through theFSSpec, an FSSpec record for the preferences file for the specified application.
- //
- // If the returned OSErr is noErr, then the preferences file exists in the location specified by theFSSpec;
- // if it's fnfErr, the preferences file does not exist but you could use theFSSpec to create a new file in
- // the specified location. If the returned OSErr is neither noErr nor fnfErr, the preferences file does not
- // exist and you should not use theFSSpec to create a new preferences file.
- //
- //////////
-
- static OSErr VRPrefs_GetPrefsFileFSSpec (char *theFileName, FSSpecPtr theFSSpec)
- {
- short myVRefNum;
- long myPrefsDirID;
- long mySystemDirID;
- Boolean myHasPrefsDir = false;
- Boolean myFoundFile = false;
- StringPtr myName = QTUtils_ConvertCToPascalString(theFileName);
- OSErr myErr = paramErr;
-
- if (theFSSpec == NULL)
- goto bail;
-
- // get the Preferences folder directory ID
- myErr = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, &myVRefNum, &myPrefsDirID);
- myHasPrefsDir = (myErr == noErr);
-
- // get the System folder directory ID
- myErr = FindFolder(kOnSystemDisk, kSystemFolderType, kDontCreateFolder, &myVRefNum, &mySystemDirID);
- if (myErr != noErr)
- goto bail; // no use in continuing if we cannot find the System folder
-
- // see if the preferences file exists in the Preferences folder
- if (myHasPrefsDir) {
- myErr = FSMakeFSSpec(myVRefNum, myPrefsDirID, myName, theFSSpec);
- if (myErr == noErr)
- myFoundFile = true;
- }
-
- // if it's not in Preferences folder, see if the preferences file exists in the System folder
- if (!myFoundFile) {
- myErr = FSMakeFSSpec(myVRefNum, mySystemDirID, myName, theFSSpec);
- if (myErr == noErr)
- myFoundFile = true;
- }
-
- // if we still haven't found a preferences file and if the Preferences folder exists,
- // then that's where we want the caller to create one
- if ((!myFoundFile) && (myHasPrefsDir))
- myErr = FSMakeFSSpec(myVRefNum, myPrefsDirID, myName, theFSSpec);
-
- bail:
- free(myName);
- return(myErr);
- }
- #endif
-
-
- //////////
- //
- // VRPrefs_ReadPrefsFile
- // Read the data from the preferences file.
- //
- //////////
-
- static void VRPrefs_ReadPrefsFile (void)
- {
- #if TARGET_OS_WIN32
- char mySubKeyName[] = kVRPrefs_PrefsKeyName;
- HKEY myKey;
- DWORD myType;
- DWORD myValue;
- DWORD mySize;
- char myBuffer[MAX_PATH];
-
- if (RegOpenKeyEx(HKEY_CURRENT_USER, mySubKeyName, 0L, KEY_ALL_ACCESS, &myKey) == ERROR_SUCCESS) {
- mySize = sizeof(DWORD);
- if (RegQueryValueEx(myKey, kVRPrefs_ScriptLocTypeLabel, NULL, &myType, (BYTE *)&myValue, &mySize) == ERROR_SUCCESS)
- (**gPreferences).fScriptLocType = (UInt32)myValue;
-
- mySize = MAX_PATH;
- if (RegQueryValueEx(myKey, kVRPrefs_ScriptPathNameLabel, NULL, &myType, (BYTE *)myBuffer, &mySize) == ERROR_SUCCESS) {
- BlockMove(myBuffer, (void *)&((**gPreferences).fScriptPathName[1]), mySize);
- (**gPreferences).fScriptPathName[0] = mySize;
- }
-
- mySize = sizeof(DWORD);
- if (RegQueryValueEx(myKey, kVRPrefs_ScriptNameTypeLabel, NULL, &myType, (BYTE *)&myValue, &mySize) == ERROR_SUCCESS)
- (**gPreferences).fScriptNameType = (UInt32)myValue;
-
- mySize = MAX_PATH;
- if (RegQueryValueEx(myKey, kVRPrefs_ScriptBaseNameLabel, NULL, &myType, (BYTE *)myBuffer, &mySize) == ERROR_SUCCESS) {
- BlockMove(myBuffer, (void *)&((**gPreferences).fScriptBaseName[1]), mySize);
- (**gPreferences).fScriptBaseName[0] = mySize;
- }
-
- RegCloseKey(myKey);
- }
- #endif
-
- #if TARGET_OS_MAC
- FSSpec myFSSpec;
- short myRefNum = 0;
- long mySize = 0;
- OSErr myErr = noErr;
-
- // find the location of the preferences file
- myErr = VRPrefs_GetPrefsFileFSSpec(kVRPrefs_PrefsFileName, &myFSSpec);
- if (myErr != noErr)
- goto bail;
-
- // open the file
- myErr = FSpOpenDF(&myFSSpec, fsRdWrPerm, &myRefNum);
-
- if (myErr == noErr)
- myErr = SetFPos(myRefNum, fsFromStart, 0);
-
- // get the size of the file data
- if (myErr == noErr)
- myErr = GetEOF(myRefNum, &mySize);
-
- // make sure that the file is at least as large as what we're expecting
- if (mySize < GetHandleSize((Handle)gPreferences))
- myErr = paramErr;
-
- HLock((Handle)gPreferences);
-
- // read the data from the file into the handle
- if (myErr == noErr)
- myErr = FSRead(myRefNum, &mySize, *gPreferences);
-
- bail:
- HUnlock((Handle)gPreferences);
-
- if (myRefNum != 0)
- FSClose(myRefNum);
- #endif
- }
-
-
- //////////
- //
- // VRPrefs_UpdatePrefsFile
- // Update the preferences file.
- //
- //////////
-
- static void VRPrefs_UpdatePrefsFile (void)
- {
- #if TARGET_OS_WIN32
- char mySubKeyName[] = kVRPrefs_PrefsKeyName;
- HKEY myKey;
- DWORD myAction;
- char *myPathName = QTUtils_ConvertPascalToCString((**gPreferences).fScriptPathName);
- char *myBaseName = QTUtils_ConvertPascalToCString((**gPreferences).fScriptBaseName);
-
- if (RegCreateKeyEx(HKEY_CURRENT_USER, mySubKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &myKey, &myAction) == ERROR_SUCCESS) {
- RegSetValueEx(myKey, kVRPrefs_ScriptLocTypeLabel, 0L, REG_DWORD, (BYTE *)&((**gPreferences).fScriptLocType), sizeof(DWORD));
- RegSetValueEx(myKey, kVRPrefs_ScriptPathNameLabel, 0L, REG_SZ, (BYTE *)myPathName, strlen(myPathName));
- RegSetValueEx(myKey, kVRPrefs_ScriptNameTypeLabel, 0L, REG_DWORD, (BYTE *)&((**gPreferences).fScriptNameType), sizeof(DWORD));
- RegSetValueEx(myKey, kVRPrefs_ScriptBaseNameLabel, 0L, REG_SZ, (BYTE *)myBaseName, strlen(myBaseName));
- RegCloseKey(myKey);
- }
-
- free(myPathName);
- free(myBaseName);
- #endif
-
- #if TARGET_OS_MAC
- FSSpec myFSSpec;
- short myRefNum = 0;
- short myVolNum;
- long mySize = 0;
- OSErr myErr = noErr;
-
- // find the location of the preferences file
- myErr = VRPrefs_GetPrefsFileFSSpec(kVRPrefs_PrefsFileName, &myFSSpec);
- if ((myErr != noErr) && (myErr != fnfErr))
- goto bail;
-
- mySize = GetHandleSize((Handle)gPreferences);
- if (mySize == 0)
- goto bail;
-
- HLock((Handle)gPreferences);
-
- // if the preferences file doesn't exist yet, then create it
- if (!(**gPreferences).fPrefsFileExists)
- myErr = FSpCreate(&myFSSpec, kScriptFileCreator, kPrefsFileType, smSystemScript);
-
- // open the file
- if (myErr == noErr)
- myErr = FSpOpenDF(&myFSSpec, fsRdWrPerm, &myRefNum);
-
- // position the file mark to the beginning of the file and write the data
- if (myErr == noErr)
- myErr = SetFPos(myRefNum, fsFromStart, 0);
-
- if (myErr == noErr)
- myErr = FSWrite(myRefNum, &mySize, *gPreferences);
-
- if (myErr == noErr)
- myErr = SetFPos(myRefNum, fsFromStart, mySize);
-
- // resize the file to the number of bytes written
- if (myErr == noErr)
- myErr = SetEOF(myRefNum, mySize);
-
- // close the file
- if (myErr == noErr)
- myErr = FSClose(myRefNum);
-
- // flush the volume
- if (myErr == noErr)
- myErr = GetVRefNum(myRefNum, &myVolNum);
-
- if (myErr == noErr)
- myErr = FlushVol(NULL, myVolNum);
-
- bail:
- HUnlock((Handle)gPreferences);
- #endif
- }
-
-
-